import path from 'path'
import marked from 'marked'

/**
 * 记录一篇笔记
 * @class
 */
export default class Note {
  readonly id: string // ID
  readonly created: number // 创建时间的时间戳

  title: string // 标题
  content: string // 内容（Markdown格式）
  originalContent: string | null // 笔记的原始内容，null 表示文件内容还未读取
  textChanged: boolean = false // Markdown 内容是否修改过
  favorite: boolean // 是否标记为收藏
  filePath: string | null = null // 文件路径

  /**
   * @param {Object} obj 用于初始化 Note 字段的对象，须包含 Note 的所有字段
   */
  constructor(obj: object)

  /**
   * @param {number} length 加入到笔记标题中的一个数字
   */
  constructor(length: number)

  /**
   * @param {string} filePath 笔记文件的路径
   * @param {string} content 文件的内容
   */
  constructor(filePath: string, content: string)

  /**
   * @constructor
   * @param para 支持多种类型的构造函数参数
   */
  constructor(...para: any[]) {
    const time = Date.now()
    const content =
      '**Hi!** This notebook is using [markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) for formatting!'

    if (para.length == 1 && typeof para[0] == 'number') {
      // 参数为数值
      this.id = String(time)
      this.title = 'New note ' + (para[0] + 1)
      this.content = content
      this.originalContent = content
      this.created = time
      this.favorite = false
      this.filePath = null
    } else if (para.length == 1 && typeof para[0] == 'object') {
      // 参数为对象
      this.title = (para[0].title && String(para[0].title)) || 'New note'
      this.favorite = !!para[0].favorite
      this.filePath = (para[0].filePath && String(para[0].filePath)) || null

      let originalContent = para[0].content && String(para[0].content)
      if (originalContent) {
        this.content = originalContent
        this.originalContent = this.content
      } else {
        this.content = ''
        this.originalContent = null
      }

      let id, created
      // 注意，这里读取参数的 id 和 created 属性，而不是 _id 和 _created
      if (
        para[0].id &&
        para[0].created &&
        para[0].id === String(para[0].created)
      ) {
        if (
          typeof para[0].created == 'number' &&
          para[0].created > 0 &&
          para[0].created <= time
        ) {
          id = para[0].id
          created = para[0].created
        }
      }
      this.id = id || String(time)
      this.created = created || time
    } else if (
      para.length == 2 &&
      typeof para[0] == 'string' &&
      typeof para[1] == 'string'
    ) {
      this.id = String(time)
      this.title = path.basename(para[0])
      this.content = para[1]
      this.originalContent = this.content
      this.created = time
      this.favorite = false
      this.filePath = para[0]
    } else {
      throw new Error('参数类型错误')
    }
  }

  public toJSON() {
    const json: any = {
      id: this.id,
      created: this.created,
      title: this.title,
      favorite: this.favorite,
    }
    if (this.filePath) {
      json.filePath = this.filePath
    } else {
      json.content = this.content
    }
    return json
  }

  /**
   * 恢复笔记内容
   */
  revert() {
    if (this.originalContent) {
      this.content = this.originalContent
      this.textChanged = false
    }
  }

  /**
   * 笔记的 HTML 文本
   * @public
   * @type {string}
   */
  public get preview(): string {
    return marked(this.content)
  }

  /**
   * 笔记的总行数
   * @public
   * @type {number}
   */
  public get linesCount(): number {
    return this.content.split(/\r\n|\r|\n/).length
  }

  /**
   * 笔记的总字数
   * @public
   * @type {number}
   */
  public get wordsCount(): number {
    let s = this.content
    // 将换行符转换为空格
    s = s.replace(/\n/g, ' ')
    // 排除开头和结尾的空格
    s = s.replace(/(^\s*)|(\s*$)/gi, '')
    // 将多个重复空格转换为一个
    s = s.replace(/\s\s+/gi, ' ')
    // 返回空格数量
    return s.split(' ').length
  }
}
